#include "asm/timer_pwm.h"


static const u32 TIMERx_table[4] = {
    (u32)JL_TIMER0,
    (u32)JL_TIMER1,
    (u32)JL_TIMER2,
    (u32)JL_TIMER3,
};

static const u32 timer_pwm_hw_io[4] = {
    IO_PORTA_05,
    IO_PORTA_12,
    IO_PORTB_03,
    IO_PORTB_05,
};

/**
 * @param JL_TIMERx : JL_TIMER0/1/2/3/4/5
 * @param fre : 频率，单位Hz
 * @param duty : 初始占空比，0~10000对应0~100%
 * @param pwm_io : JL_PORTA_01, JL_PORTB_02,,,等等，建议填硬件IO
 * @param output_ch : 映射通道，当pwm脚选择非硬件脚时有效，这时我们给他分配output_channel 0/1/2
 */
void timer_pwm_init(JL_TIMER_TypeDef *JL_TIMERx, u32 fre, u32 duty, u32 pwm_io, u8 output_ch)
{
    u8 tmr_num;
    for (tmr_num = 0; tmr_num < 4; tmr_num ++) {
        if ((u32)JL_TIMERx == TIMERx_table[tmr_num]) {
            break;
        }
        if (tmr_num == 3) {
            return;
        }
    }
    u32 timer_clk = clk_get("lsb");
    if (tmr_num == 3) {
        bit_clr_ie(IRQ_TIME3_IDX);
    }
    //初始化timer
    JL_TIMERx->CON = 0;
    JL_TIMERx->CON |= (0b00 << 2);                  //时钟源选择LSB_CLK
    JL_TIMERx->CON |= (0b0001 << 4);				//时钟源再4分频
    JL_TIMERx->CNT = 0;								//清计数值
    JL_TIMERx->PRD = timer_clk / (4 * fre);			//设置周期
    //设置初始占空比
    JL_TIMERx->PWM = (JL_TIMERx->PRD * duty) / 10000;	//0~10000对应0~100%

    JL_TIMERx->CON |= (0b01 << 0); 			        //计数模式

    if (pwm_io == timer_pwm_hw_io[tmr_num]) {
        gpio_set_die(pwm_io, 1);
        gpio_set_pull_up(pwm_io, 0);
        gpio_set_pull_down(pwm_io, 0);
        gpio_set_direction(pwm_io, 0);
        JL_TIMERx->CON |= BIT(8);                   //计数模式
    } else {
        gpio_output_channel(pwm_io, output_ch);
    }
}

/**
 * @param JL_TIMERx : JL_TIMER0/1/2/3
 * @param duty : 占空比，0~10000对应0~100%
 */
void set_timer_pwm_duty(JL_TIMER_TypeDef *JL_TIMERx, u32 duty)
{
    JL_TIMERx->PWM = (JL_TIMERx->PRD * duty) / 10000;	//0~10000对应0~100%
}

/**
 * @param JL_TIMERx : JL_TIMER0/1/2/3
 */
void close_timer_pwm(JL_TIMER_TypeDef *JL_TIMERx)
{
    JL_TIMERx->CON &= ~(BIT(8) | BIT(0));
}


/********************************* 以下SDK的参考示例 ****************************/

void timer_pwm_test(void)
{
    printf("*********** timer pwm test *************\n");

    timer_pwm_init(JL_TIMER2, 1000, 5000, IO_PORTB_03, 0);              //1KHz 50%
    timer_pwm_init(JL_TIMER3, 10000, 7500, IO_PORTA_03, CH2_T3_PWM_OUT);//非硬件IO 10KHz 75%

#if 0
    extern void wdt_clear();
    while (1) {
        wdt_clear();
    }
#endif
}
